home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume20 / pcomm1.2 / part07 < prev    next >
Encoding:
Internet Message Format  |  1989-10-25  |  55.5 KB

  1. Subject:  v20i073:  Pcomm telecommunication package, Part07/08
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: fthood!egray
  7. Posting-number: Volume 20, Issue 73
  8. Archive-name: pcomm1.2/part07
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create:
  15. #    terminal.c
  16. #    tty_att.c
  17. #    tty_ucb.c
  18. #    vcs.c
  19. #    vcs.h
  20. #    waitfor.c
  21. #    x_ascii.c
  22. #    x_batch.c
  23. #    x_extrnl.c
  24. export PATH; PATH=/bin:/usr/bin:$PATH
  25. echo shar: "extracting 'terminal.c'" '(9863 characters)'
  26. if test -f 'terminal.c'
  27. then
  28.     echo shar: "will not over-write existing file 'terminal.c'"
  29. else
  30. sed 's/^X//' << \SHAR_EOF > 'terminal.c'
  31. X/*
  32. X * Start the terminal dialogue, fork the input routine, watch for the
  33. X * hot key so we can execute an option.
  34. X */
  35. X
  36. X#include <stdio.h>
  37. X#include <curses.h>
  38. X#include <signal.h>
  39. X#include "config.h"
  40. X#include "dial_dir.h"
  41. X#include "misc.h"
  42. X#include "modem.h"
  43. X#include "param.h"
  44. X#include "status.h"
  45. X#include "xmodem.h"
  46. X
  47. X#ifdef UNIXPC
  48. X#include <sys/phone.h>
  49. X#include <fcntl.h>
  50. X#endif /* UNIXPC */
  51. X
  52. Xstatic int pid = -1;
  53. X
  54. Xterminal(extra_dir, input_status)
  55. Xchar *extra_dir;
  56. Xint input_status;
  57. X{
  58. X    extern int fd;
  59. X    int i, j, k, cr_lf, script;
  60. X    char c, lf=10, *str_rep(), *keymac, *memset();
  61. X    void help_screen(), line_set(), n_shell(), load_vs(), send_str();
  62. X    void release_port(), do_input(), list_dir(), pexit(), zap_vs();
  63. X    void st_line(), chg_dir(), screen_dump(), input_off(), suspend();
  64. X    void info(), term_mode(), macro(), do_script();
  65. X
  66. X                    /* if starting out in command mode */
  67. X    if (!input_status) {
  68. X        erase();
  69. X        refresh();
  70. X        st_line("");
  71. X    }
  72. X                    /* put stdin/stdout in terminal mode */
  73. X    resetterm();
  74. X    term_mode();
  75. X    cr_lf = !strcmp(param->cr_out, "CR/LF");
  76. X
  77. X    if (input_status) {
  78. X        do_script(extra_dir);
  79. X        do_input();
  80. X    }
  81. X
  82. X    while (1) {
  83. X        read(0, &c, 1);
  84. X        c &= 0x7f;
  85. X                    /* is it the hot key? */
  86. X        if (c == param->hot) {
  87. X                    /* suspend input */
  88. X            input_status = 0;
  89. X            suspend(TRUE);
  90. X            script = 0;
  91. X
  92. X            /*
  93. X             * Put the terminal in the curses mode, load the
  94. X             * virtual screen and add the status line at the bottom.
  95. X             */
  96. X            fixterm();
  97. X            load_vs();
  98. X            st_line("");
  99. X#ifndef OLDCURSES
  100. X            keypad(stdscr, TRUE);
  101. X#endif /* OLDCURSES */
  102. X            i = wgetch(stdscr);
  103. X                    /* map an additional hot key to -1 */
  104. X            if (i == param->hot)
  105. X                i = -1;
  106. X
  107. X            keymac = "";
  108. X                    /* look for options */
  109. X            k = -1;
  110. X            switch (i) {
  111. X                case -1:    /* 2 "hots" means send 1 */
  112. X                    k = param->hot;
  113. X                    break;
  114. X                case '0':    /* help screen */
  115. X                    help_screen(param->ascii_hot);
  116. X                    break;
  117. X                case 'd':
  118. X                case 'D':    /* dialing directory */
  119. X                    if (dial_menu())
  120. X                        input_status = dial_win();
  121. X                    script = input_status;
  122. X                    break;
  123. X                case 'r':
  124. X                case 'R':    /* redial */
  125. X                    if (redial())
  126. X                        input_status = dial_win();
  127. X                    script = input_status;
  128. X                    break;
  129. X                case 'm':
  130. X                case 'M':    /* keyboard macros */
  131. X                    macro();
  132. X                    break;
  133. X                case 'p':
  134. X                case 'P':    /* line settings */
  135. X                    if (ls_menu())
  136. X                        line_set();
  137. X                    break;
  138. X                case 'x':
  139. X                case 'X':    /* exit */
  140. X                    pexit();
  141. X                    break;
  142. X                case '4':    /* Unix gateway */
  143. X                    n_shell();
  144. X                    break;
  145. X                case 'i':
  146. X                case 'I':    /* program info screen */
  147. X                    info(MANUAL_CLEAR);
  148. X                    break;
  149. X                case 's':    /* setup menu */
  150. X                case 'S':
  151. X                    input_status = setup_menu();
  152. X                    break;
  153. X                case 'c':    /* clear the screen */
  154. X                case 'C':
  155. X                    zap_vs();
  156. X                    erase();
  157. X#ifdef SHAREDMEM
  158. X                    if (pid == -1) {
  159. X                        for (j=0; j<LINES; j++)
  160. X                            memset(status->vs[j], ' ', COLS);
  161. X                    }
  162. X#endif /* SHAREDMEM */
  163. X                    break;
  164. X                case 'b':
  165. X                case 'B':    /* change directory */
  166. X                    chg_dir();
  167. X                    break;
  168. X                case 'e':
  169. X                case 'E':    /* toggle duplex */
  170. X                    if (dir->duplex[dir->d_cur] == 'F')
  171. X                        dir->duplex[dir->d_cur] = 'H';
  172. X                    else
  173. X                        dir->duplex[dir->d_cur] = 'F';
  174. X
  175. X                        /* show changes */
  176. X                    st_line("");
  177. X                    k = wait_key(stdscr, 2);
  178. X                    break;
  179. X                case 'h':
  180. X                case 'H':    /* hang up phone */
  181. X                    release_port(VERBOSE);
  182. X                    input_off();
  183. X                    break;
  184. X                case 'l':
  185. X                case 'L':    /* toggle printer */
  186. X                    status->print = status->print ? 0 : 1;
  187. X#ifndef SHAREDMEM
  188. X                    if (pid != -1)
  189. X                        kill(pid, SIGUSR2);
  190. X#endif /* SHAREDMEM */
  191. X                        /* show changes */
  192. X                    st_line("");
  193. X                    k = wait_key(stdscr, 2);
  194. X                    break;
  195. X                case '3':    /* toggle CR - CR/LF */
  196. X                    if (!strcmp(param->cr_in, "CR")) {
  197. X                        param->cr_in = str_rep(param->cr_in, "CR/LF");
  198. X                        status->add_lf = 1;
  199. X                    }
  200. X                    else {
  201. X                        param->cr_in = str_rep(param->cr_in, "CR");
  202. X                        status->add_lf = 0;
  203. X                    }
  204. X#ifndef SHAREDMEM
  205. X                    input_off();
  206. X                    input_status++;
  207. X#endif /* SHAREDMEM */
  208. X                        /* show changes */
  209. X                    st_line("");
  210. X                    k = wait_key(stdscr, 2);
  211. X                    break;
  212. X                case '7':    /* break key */
  213. X                    if (fd != -1)
  214. X                        tty_break(fd);
  215. X
  216. X                    st_line("   break");
  217. X                    break;
  218. X#ifndef OLDCURSES
  219. X                case KEY_UP:
  220. X#endif /* OLDCURSES */
  221. X                case 'u':
  222. X                case 'U':    /* send files */
  223. X                    input_status = xfer_menu(UP_LOAD);
  224. X                    break;
  225. X#ifndef OLDCURSES
  226. X                case KEY_DOWN:
  227. X                case '\n':
  228. X#endif /* OLDCURSES */
  229. X                case 'n':
  230. X                case 'N':    /* receive files */
  231. X                    input_status = xfer_menu(DOWN_LOAD);
  232. X                    break;
  233. X                case 't':
  234. X                case 'T':
  235. X                    input_status = pass_thru();
  236. X                    break;
  237. X                case 'f':
  238. X                case 'F':    /* list directory */
  239. X                    list_dir();
  240. X                    break;
  241. X                case 'g':    /* screen dump */
  242. X                case 'G':
  243. X                    screen_dump();
  244. X                    st_line(" screen dump");
  245. X                    k = wait_key(stdscr, 2);
  246. X                    break;
  247. X                case '1':    /* data logging */
  248. X                    input_status = data_logging();
  249. X                    break;
  250. X                case '2':    /* toggle log */
  251. X                    if (!strcmp(status->log_path, "NOT_DEFINED")) {
  252. X                        beep();
  253. X                        st_line(" no log file");
  254. X                        k = wait_key(stdscr, 2);
  255. X                        break;
  256. X                    }
  257. X                    status->log = status->log ? 0 : 1;
  258. X#ifndef SHAREDMEM
  259. X                    if (pid != -1)
  260. X                        kill(pid, SIGUSR1);
  261. X#endif /* SHAREDMEM */
  262. X                        /* show changes */
  263. X                    st_line("");
  264. X                    k = wait_key(stdscr, 2);
  265. X                    break;
  266. X                /*
  267. X                 * The following are the keyboard macros
  268. X                 * corresponding to the shifted number keys.
  269. X                 * (Too many keys... [control] [A] [shift] [1]
  270. X                 * is hardly a shortcut!)
  271. X                 */
  272. X                case '!':
  273. X                    keymac = param->mac_1;
  274. X                    break;
  275. X                case '@':
  276. X                    keymac = param->mac_2;
  277. X                    break;
  278. X                case '#':
  279. X                    keymac = param->mac_3;
  280. X                    break;
  281. X                case '$':
  282. X                    keymac = param->mac_4;
  283. X                    break;
  284. X                case '%':
  285. X                    keymac = param->mac_5;
  286. X                    break;
  287. X                case '^':
  288. X                    keymac = param->mac_6;
  289. X                    break;
  290. X                case '&':
  291. X                    keymac = param->mac_7;
  292. X                    break;
  293. X                case '*':
  294. X                    keymac = param->mac_8;
  295. X                    break;
  296. X                case '(':
  297. X                    keymac = param->mac_9;
  298. X                    break;
  299. X                case ')':
  300. X                    keymac = param->mac_0;
  301. X                    break;
  302. X                default:
  303. X                    fputc(BEL, stderr);
  304. X                    break;
  305. X            }
  306. X
  307. X            /*
  308. X             * Repaint the stdscr (if we are already talking),
  309. X             * get the stdin/stdout out of the curses mode and
  310. X             * into the terminal mode.
  311. X             */
  312. X            if (fd != -1) {
  313. X                touchwin(stdscr);
  314. X                refresh();
  315. X            }
  316. X            resetterm();
  317. X            term_mode();
  318. X
  319. X            /*
  320. X             * Some of the output processing options have to be
  321. X             * faked...  Unfortunately, adding a LF to CR on
  322. X             * output is one of them.
  323. X             */
  324. X            cr_lf = !strcmp(param->cr_out, "CR/LF");
  325. X
  326. X                    /* run the auto-login script */
  327. X            if (script)
  328. X                do_script(extra_dir);
  329. X
  330. X                    /* re-start input routine */
  331. X            if (input_status)
  332. X                do_input();
  333. X            else
  334. X                suspend(FALSE);
  335. X
  336. X                    /* send the macro */
  337. X            if (*keymac != '\0')
  338. X                send_str(keymac, FAST);
  339. X            /*
  340. X             * If you pressed a key during one of the sleeping
  341. X             * periods (typically the delay to see the status
  342. X             * line change), let the keyboard value fall thru
  343. X             * to the write() below.
  344. X             */
  345. X            if (k == -1)
  346. X                continue;
  347. X            c = k;
  348. X        }
  349. X                    /* ignore errors if fd == -1 */
  350. X        write(fd, &c, 1);
  351. X                    /* map cr to cr_lf? */
  352. X        if (c == '\r' && cr_lf)
  353. X            write(fd, &lf, 1);
  354. X    }
  355. X}
  356. X
  357. X/*
  358. X * Fire up the input routine...
  359. X */
  360. X
  361. Xvoid
  362. Xdo_input()
  363. X{
  364. X    extern int fd;
  365. X    void error_win();
  366. X    char first[(sizeof(int)*8)+1];
  367. X#ifdef SHAREDMEM
  368. X    extern int shm_id;
  369. X#else /* SHAREDMEM */
  370. X    char add_lf[2], log[2], print[2], dup_fd[3];
  371. X#endif /* SHAREDMEM */
  372. X                    /* if no TTY, or already on */
  373. X    if (pid != -1 || fd == -1)
  374. X        return;
  375. X
  376. X    status->fd = fd;
  377. X    status->add_lf = !strcmp(param->cr_in, "CR/LF");
  378. X
  379. X#ifdef SHAREDMEM
  380. X    sprintf(first, "%d", shm_id);
  381. X#else /* SHAREDMEM */
  382. X    sprintf(first, "%d", status->fd);
  383. X    sprintf(dup_fd, "%d", status->dup_fd);
  384. X    sprintf(add_lf, "%d", status->add_lf);
  385. X    sprintf(log, "%d", status->log);
  386. X    sprintf(print, "%d", status->print);
  387. X#endif /* SHAREDMEM */
  388. X
  389. X                    /* fork the input routine */
  390. X    if (!(pid = fork())) {
  391. X#ifdef BSD
  392. X        setpgrp(0, getpid());
  393. X#else /* BSD */
  394. X        setpgrp();
  395. X#endif /* BSD */
  396. X
  397. X#ifdef SETUGID
  398. X        setuid(getuid());
  399. X        setgid(getgid());
  400. X#endif /* SETUGID */
  401. X
  402. X#ifdef SHAREDMEM
  403. X        execlp("pcomm_input", "pcomm_input", first, (char *) 0);
  404. X#else /* SHAREDMEM */
  405. X        execlp("pcomm_input", "pcomm_input", first, dup_fd, add_lf,
  406. X         log, print, status->log_path, status->vs_path, (char *) 0);
  407. X#endif /* SHAREDMEM */
  408. X        error_win(1, "Cannot find (or execute) the 'pcomm_input' program", "");
  409. X    }
  410. X
  411. X    return;
  412. X}
  413. X
  414. X/*
  415. X * shut it down...
  416. X */
  417. X
  418. Xvoid
  419. Xinput_off()
  420. X{
  421. X    if (pid != -1) {
  422. X        kill(pid, SIGTERM);
  423. X        pid = -1;
  424. X    }
  425. X    return;
  426. X}
  427. X
  428. X/*
  429. X * Hang up the phone but remain in the Pcomm command state.  Uses the
  430. X * hang_up string only, does *not* drop the DTR!
  431. X */
  432. X
  433. Xvoid
  434. Xhang_up(verbose)
  435. Xint verbose;
  436. X{
  437. X    extern int fd;
  438. X    void send_str(), st_line(), line_set();
  439. X    char buf[80], *strcpy(), *ttyname();
  440. X                    /* sanity checking */
  441. X    if (modem == NULL)
  442. X        return;
  443. X                    /* anything to hang up? */
  444. X    if (modem->m_cur == -1 || fd == -1)
  445. X        return;
  446. X
  447. X    if (verbose)
  448. X        st_line("disconnecting");
  449. X                    /* special case for OBM */
  450. X#ifdef UNIXPC
  451. X    if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
  452. X        ioctl(fd, PIOCDISC);
  453. X        /*
  454. X         * The PIOCDISC ioctl screws up the file descriptor!!!
  455. X         * No other phone(7) ioctl can fix it.  Whatever it does,
  456. X         * it seems to escape detection with PIOCGETA and TCGETA.
  457. X         * The best I can do is close the port and start over.
  458. X         */
  459. X        strcpy(buf, ttyname(fd));
  460. X        close(fd);
  461. X        fd = open(buf, O_RDWR|O_NDELAY);
  462. X        line_set();
  463. X        fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
  464. X    }
  465. X    else
  466. X#endif /* UNIXPC */
  467. X        send_str(modem->hang_up[modem->m_cur], SLOW);
  468. X
  469. X    if (verbose)
  470. X        st_line("");
  471. X    return;
  472. X}
  473. X
  474. X/*
  475. X * Suspend or un-suspend the input routine.  The argument is used in
  476. X * non-shared memory configurations to give the vs_path file a fighting
  477. X * chance of being written to disk before load_vs() reads it.
  478. X */
  479. X
  480. X/* ARGSUSED */
  481. Xvoid
  482. Xsuspend(on)
  483. Xint on;
  484. X{
  485. X    unsigned int sleep();
  486. X
  487. X    if (pid == -1)
  488. X        return;
  489. X    kill(pid, SIGINT);
  490. X
  491. X#ifndef SHAREDMEM
  492. X    if (on)
  493. X        sleep(1);
  494. X#endif /* SHAREDMEM */
  495. X
  496. X    return;
  497. X}
  498. SHAR_EOF
  499. if test 9863 -ne "`wc -c < 'terminal.c'`"
  500. then
  501.     echo shar: "error transmitting 'terminal.c'" '(should have been 9863 characters)'
  502. fi
  503. fi
  504. echo shar: "extracting 'tty_att.c'" '(4795 characters)'
  505. if test -f 'tty_att.c'
  506. then
  507.     echo shar: "will not over-write existing file 'tty_att.c'"
  508. else
  509. sed 's/^X//' << \SHAR_EOF > 'tty_att.c'
  510. X/*
  511. X * System V specific routines for manipulating the TTY
  512. X */
  513. X
  514. X#include <stdio.h>
  515. X#include <termio.h>
  516. X#include <fcntl.h>
  517. X#include "dial_dir.h"
  518. X#include "param.h"
  519. X
  520. X/*
  521. X * Change the communication line settings to the new values.
  522. X */
  523. X
  524. Xvoid
  525. Xline_set()
  526. X{
  527. X    extern int fd;
  528. X    struct termio tbuf;
  529. X
  530. X    /*
  531. X     * The manual dial entry also serves to store the previous
  532. X     * line settings.  How else would the manual dial entry
  533. X     * know what line setting to use?
  534. X     */
  535. X    if (dir->d_cur != 0) {
  536. X        dir->baud[0] = dir->baud[dir->d_cur];
  537. X        dir->parity[0] = dir->parity[dir->d_cur];
  538. X        dir->dbits[0] = dir->dbits[dir->d_cur];
  539. X        dir->sbits[0] = dir->sbits[dir->d_cur];
  540. X    }
  541. X                    /* nothing to do! */
  542. X    if (fd == -1)
  543. X        return;
  544. X                    /* get the current settings */
  545. X    ioctl(fd, TCGETA, &tbuf);
  546. X                    /* set some beginning values */
  547. X    tbuf.c_cc[4] = 1;        /* VMIN */
  548. X    tbuf.c_cc[5] = 0;        /* VTIME */
  549. X    tbuf.c_oflag = 0;
  550. X    tbuf.c_iflag = 0;
  551. X    tbuf.c_cflag = (CREAD|HUPCL|CLOCAL);
  552. X    tbuf.c_lflag = 0;
  553. X
  554. X    if (*param->flow == 'X')
  555. X        tbuf.c_iflag |= (IXON|IXOFF);
  556. X                    /* strip high bit? */
  557. X    if (*param->strip == 'Y')
  558. X        tbuf.c_iflag |= ISTRIP;
  559. X                    /* the baud rate */
  560. X    switch (dir->baud[dir->d_cur]) {
  561. X        case 300:
  562. X            tbuf.c_cflag |= B300;
  563. X            break;
  564. X        case 1200:
  565. X            tbuf.c_cflag |= B1200;
  566. X            break;
  567. X        case 2400:
  568. X            tbuf.c_cflag |= B2400;
  569. X            break;
  570. X        case 4800:
  571. X            tbuf.c_cflag |= B4800;
  572. X            break;
  573. X        case 9600:
  574. X            tbuf.c_cflag |= B9600;
  575. X            break;
  576. X        case 19200:
  577. X#ifdef B19200
  578. X            tbuf.c_cflag |= B19200;
  579. X#else /* B19200 */
  580. X#ifdef EXTA
  581. X            tbuf.c_cflag |= EXTA;
  582. X#endif /* EXTA */
  583. X#endif /* B19200 */
  584. X            break;
  585. X    }
  586. X                    /* the parity */
  587. X    switch (dir->parity[dir->d_cur]) {
  588. X        case 'N':
  589. X            break;
  590. X        case 'O':
  591. X            tbuf.c_cflag |= (PARENB|PARODD);
  592. X            break;
  593. X        case 'E':
  594. X            tbuf.c_cflag |= PARENB;
  595. X            break;
  596. X    }
  597. X                    /* the data bits */
  598. X    if (dir->dbits[dir->d_cur] == 8)
  599. X        tbuf.c_cflag |= CS8;
  600. X    else
  601. X        tbuf.c_cflag |= CS7;
  602. X                    /* the stop bits */
  603. X    if (dir->sbits[dir->d_cur] == 2)
  604. X        tbuf.c_cflag |= CSTOPB;
  605. X
  606. X                    /* now set 'em! */
  607. X    ioctl(fd, TCSETAF, &tbuf);
  608. X    return;
  609. X}
  610. X
  611. X/*
  612. X * Put the stdin/stdout in terminal mode.  We've divided up the
  613. X * responsibility for the line settings options between the serial port
  614. X * and the stdin and stdout.
  615. X */
  616. X
  617. Xvoid
  618. Xterm_mode()
  619. X{
  620. X    struct termio tbuf;
  621. X
  622. X    ioctl(0, TCGETA, &tbuf);
  623. X
  624. X    tbuf.c_cc[4] = 1;        /* VMIN */
  625. X    tbuf.c_cc[5] = 0;        /* VTIME */
  626. X    tbuf.c_iflag = 0;
  627. X    tbuf.c_oflag = 0;
  628. X    tbuf.c_lflag = 0;
  629. X                    /* duplex */
  630. X    if (dir->duplex[dir->d_cur] == 'H')
  631. X        tbuf.c_lflag = ECHO;
  632. X
  633. X    ioctl(0, TCSETAF, &tbuf);
  634. X    return;
  635. X}
  636. X
  637. X/*
  638. X * Put the TTY driver in the mode suitable for xmodem transfers.
  639. X */
  640. X
  641. Xvoid
  642. Xxmodem_mode(fds)
  643. Xint fds;
  644. X{
  645. X    struct termio tbuf;
  646. X
  647. X    ioctl(fds, TCGETA, &tbuf);
  648. X    /*
  649. X     * Turn off the XON/XOFF flow control, turn off echoing, and
  650. X     * switch to 8 bit no parity.
  651. X     */
  652. X    tbuf.c_cc[4] = 1;        /* VMIN */
  653. X    tbuf.c_cc[5] = 0;        /* VTIME */
  654. X    tbuf.c_iflag = 0;        /* no flow control or mapping */
  655. X    tbuf.c_oflag = 0;        /* no char mapping or delays */
  656. X    tbuf.c_lflag = 0;        /* no echo or signals */
  657. X    tbuf.c_cflag &= ~(PARENB|CSIZE);/* no parity */
  658. X    tbuf.c_cflag |= CS8;        /* 8 bit */
  659. X
  660. X    ioctl(fds, TCSETAF, &tbuf);
  661. X    return;
  662. X}
  663. X
  664. X/*
  665. X * Put the TTY line in a mode suitable for the ASCII transfer.  Puts the
  666. X * terminal in the raw, non-blocking mode.
  667. X */
  668. X
  669. Xvoid
  670. Xascii_mode(up)
  671. Xint up;
  672. X{
  673. X    extern int fd;
  674. X    struct termio tbuf;
  675. X
  676. X    ioctl(fd, TCGETA, &tbuf);
  677. X    tbuf.c_oflag = 0;
  678. X                    /* flow control & 8th bit stripping */
  679. X    if (up) {
  680. X        tbuf.c_iflag = (ISTRIP|IXON);
  681. X
  682. X                    /* if no CR's, use NL delays */
  683. X        if (!strcmp(param->cr_up, "STRIP"))
  684. X            tbuf.c_oflag = (OPOST|ONLRET);
  685. X
  686. X                    /* CR delay times */
  687. X        switch (param->cr_delay) {
  688. X            case 0:
  689. X                break;
  690. X            case 100:
  691. X                tbuf.c_oflag |= (OPOST|CR2);
  692. X                break;
  693. X            case 150:
  694. X                tbuf.c_oflag |= (OPOST|CR3);
  695. X                break;
  696. X        }
  697. X    }
  698. X                    /* if down loading */
  699. X    else
  700. X        tbuf.c_iflag = (ISTRIP|IXOFF);
  701. X
  702. X    ioctl(fd, TCSETAF, &tbuf);
  703. X    return;
  704. X}
  705. X
  706. X/*
  707. X * Flush the file descriptor
  708. X */
  709. X
  710. Xint
  711. Xtty_flush(fds, mode)
  712. Xint fds, mode;
  713. X{
  714. X    return(ioctl(fds, TCFLSH, mode));
  715. X}
  716. X
  717. X/*
  718. X * Wait for the output to drain
  719. X */
  720. X
  721. Xint
  722. Xtty_drain(fds)
  723. Xint fds;
  724. X{
  725. X    return(ioctl(fds, TCSBRK, 1));
  726. X}
  727. X
  728. X/*
  729. X * Send a modem break
  730. X */
  731. X
  732. Xint
  733. Xtty_break(fds)
  734. Xint fds;
  735. X{
  736. X    return(ioctl(fds, TCSBRK, 0));
  737. X}
  738. X
  739. X/*
  740. X * Fix the file descriptor so that a read is satisfied immediately.  When
  741. X * read() is called it returns the character in the queue, or an error if
  742. X * no key was pressed.
  743. X */
  744. X
  745. Xint
  746. Xtty_noblock(fds, on)
  747. Xint fds, on;
  748. X{
  749. X    int current;
  750. X
  751. X    current = fcntl(fds, F_GETFL, 0);
  752. X    if (on)
  753. X        return(fcntl(fds, F_SETFL, current | O_NDELAY));
  754. X    else
  755. X        return(fcntl(fds, F_SETFL, current & ~O_NDELAY));
  756. X}
  757. X
  758. X/*
  759. X * Get the current baud rate of the terminal
  760. X */
  761. X
  762. Xint
  763. Xmy_speed()
  764. X{
  765. X    static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
  766. X     1200, 1800, 2400, 4800, 9600, 19200};
  767. X    struct termio tbuf;
  768. X
  769. X    ioctl(0, TCGETA, &tbuf);
  770. X    return(speed[tbuf.c_cflag & CBAUD]);
  771. X}
  772. SHAR_EOF
  773. if test 4795 -ne "`wc -c < 'tty_att.c'`"
  774. then
  775.     echo shar: "error transmitting 'tty_att.c'" '(should have been 4795 characters)'
  776. fi
  777. fi
  778. echo shar: "extracting 'tty_ucb.c'" '(4666 characters)'
  779. if test -f 'tty_ucb.c'
  780. then
  781.     echo shar: "will not over-write existing file 'tty_ucb.c'"
  782. else
  783. sed 's/^X//' << \SHAR_EOF > 'tty_ucb.c'
  784. X/*
  785. X * Berkeley specific routines for manipulating the TTY
  786. X */
  787. X
  788. X#include <stdio.h>
  789. X#include <sgtty.h>
  790. X#include <fcntl.h>
  791. X#include "dial_dir.h"
  792. X#include "param.h"
  793. X
  794. X/*
  795. X * Change the communication line settings to the new values.
  796. X */
  797. X
  798. Xvoid
  799. Xline_set()
  800. X{
  801. X    extern int fd;
  802. X    struct sgttyb tbuf;
  803. X
  804. X    /*
  805. X     * The manual dial entry also serves to store the previous
  806. X     * line settings.  How else would the manual dial entry
  807. X     * know what line setting to use?
  808. X     */
  809. X    if (dir->d_cur != 0) {
  810. X        dir->baud[0] = dir->baud[dir->d_cur];
  811. X        dir->parity[0] = dir->parity[dir->d_cur];
  812. X        dir->dbits[0] = dir->dbits[dir->d_cur];
  813. X        dir->sbits[0] = dir->sbits[dir->d_cur];
  814. X    }
  815. X                    /* nothing to do! */
  816. X    if (fd == -1)
  817. X        return;
  818. X                    /* get the current settings */
  819. X    ioctl(fd, TIOCGETP, &tbuf);
  820. X                    /* set some beginning values */
  821. X    tbuf.sg_flags = CBREAK;
  822. X
  823. X    if (*param->flow == 'X')
  824. X        tbuf.sg_flags |= TANDEM;
  825. X                    /* the baud rate */
  826. X    switch (dir->baud[dir->d_cur]) {
  827. X        case 300:
  828. X            tbuf.sg_ispeed = B300;
  829. X            tbuf.sg_ospeed = B300;
  830. X            break;
  831. X        case 1200:
  832. X            tbuf.sg_ispeed = B1200;
  833. X            tbuf.sg_ospeed = B1200;
  834. X            break;
  835. X        case 2400:
  836. X            tbuf.sg_ispeed = B2400;
  837. X            tbuf.sg_ospeed = B2400;
  838. X            break;
  839. X        case 4800:
  840. X            tbuf.sg_ispeed = B4800;
  841. X            tbuf.sg_ospeed = B4800;
  842. X            break;
  843. X        case 9600:
  844. X            tbuf.sg_ispeed = B9600;
  845. X            tbuf.sg_ospeed = B9600;
  846. X            break;
  847. X        case 19200:
  848. X#ifdef B19200
  849. X            tbuf.sg_ispeed = B19200;
  850. X            tbuf.sg_ospeed = B19200;
  851. X#else /* B19200 */
  852. X#ifdef EXTA
  853. X            tbuf.sg_ispeed = EXTA;
  854. X            tbuf.sg_ospeed = EXTA;
  855. X#endif /* EXTA */
  856. X#endif /* B19200 */
  857. X            break;
  858. X    }
  859. X                    /* the parity */
  860. X    switch (dir->parity[dir->d_cur]) {
  861. X        case 'N':
  862. X            tbuf.sg_flags |= ANYP;
  863. X            break;
  864. X        case 'O':
  865. X            tbuf.sg_flags |= ODDP;
  866. X            break;
  867. X        case 'E':
  868. X            tbuf.sg_flags |= EVENP;
  869. X            break;
  870. X    }
  871. X                    /* now set 'em! */
  872. X    ioctl(fd, TIOCSETP, &tbuf);
  873. X    return;
  874. X}
  875. X
  876. X/*
  877. X * Put the stdin/stdout in terminal mode.  We've divided up the
  878. X * responsibility for the line settings options between the serial port
  879. X * and the stdin and stdout.
  880. X */
  881. X
  882. Xvoid
  883. Xterm_mode()
  884. X{
  885. X    struct sgttyb tbuf;
  886. X
  887. X    ioctl(0, TIOCGETP, &tbuf);
  888. X    
  889. X    tbuf.sg_flags |= CBREAK;
  890. X    tbuf.sg_flags &= ~(RAW|CRMOD|ECHO);
  891. X
  892. X    if (dir->duplex[dir->d_cur] == 'H')
  893. X        tbuf.sg_flags |= ECHO;
  894. X
  895. X    ioctl(0, TIOCSETP, &tbuf);
  896. X    return;
  897. X}
  898. X
  899. X/*
  900. X * Put the TTY driver in the mode suitable for xmodem transfers.
  901. X */
  902. X
  903. Xvoid
  904. Xxmodem_mode(fds)
  905. Xint fds;
  906. X{
  907. X    struct sgttyb tbuf;
  908. X
  909. X    ioctl(fds, TIOCGETP, &tbuf);
  910. X    /*
  911. X     * Turn off the XON/XOFF flow control, turn off echoing, and
  912. X     * switch to 8 bit no parity.
  913. X     */
  914. X    tbuf.sg_flags |= (RAW|ANYP);
  915. X    tbuf.sg_flags &= ~ECHO;
  916. X    ioctl(fds, TIOCSETP, &tbuf);
  917. X    return;
  918. X}
  919. X
  920. X/*
  921. X * Put the TTY line in a mode suitable for the ASCII transfer.
  922. X */
  923. X
  924. Xvoid
  925. Xascii_mode(up)
  926. Xint up;
  927. X{
  928. X    extern int fd;
  929. X    struct sgttyb tbuf;
  930. X
  931. X    ioctl(fd, TIOCGETP, &tbuf);
  932. X
  933. X    tbuf.sg_flags |= (CBREAK|TANDEM);
  934. X    tbuf.sg_flags &= ~(RAW|CRMOD|ECHO|CRDELAY);
  935. X
  936. X    if (up) {
  937. X                    /* CR delay times */
  938. X        switch (param->cr_delay) {
  939. X            case 0:
  940. X                break;
  941. X            case 100:
  942. X                tbuf.sg_flags |= CR1;
  943. X                break;
  944. X            case 150:
  945. X                tbuf.sg_flags |= CR2;
  946. X                break;
  947. X        }
  948. X    }
  949. X
  950. X    ioctl(fd, TIOCSETP, &tbuf);
  951. X    return;
  952. X}
  953. X
  954. X/*
  955. X * Flush the file descriptor.  Very messy... flushing the input causes a
  956. X * wait for the ouput to drain, and there is no output flushing.
  957. X */
  958. X
  959. Xint
  960. Xtty_flush(fds, mode)
  961. Xint fds, mode;
  962. X{
  963. X    int ret_code = 0;
  964. X    struct sgttyb tbuf;
  965. X
  966. X    switch(mode) {
  967. X        case 0:            /* flush input queue */
  968. X            ioctl(fds, TIOCGETP, &tbuf);
  969. X            ioctl(fds, TIOCSETP, &tbuf);
  970. X            break;
  971. X        case 1:            /* flush output queue */
  972. X            /* sorry! */
  973. X            break;
  974. X        case 2:            /* flush both input and output */
  975. X            ioctl(fds, TIOCFLUSH, 0);
  976. X            break;
  977. X        default:
  978. X            ret_code++;
  979. X            break;
  980. X    }
  981. X    return(ret_code);
  982. X}
  983. X
  984. X/*
  985. X * Wait for the output to drain
  986. X */
  987. X
  988. Xint
  989. Xtty_drain(fds)
  990. Xint fds;
  991. X{
  992. X    struct sgttyb tbuf;
  993. X                    /* this flushes the input too */
  994. X    ioctl(fds, TIOCGETP, &tbuf);
  995. X    return(ioctl(fds, TIOCSETP, &tbuf));
  996. X}
  997. X
  998. X/*
  999. X * Send a modem break
  1000. X */
  1001. X
  1002. Xint
  1003. Xtty_break(fds)
  1004. Xint fds;
  1005. X{
  1006. X    unsigned int sleep();
  1007. X
  1008. X    ioctl(fds, TIOCSBRK, (struct sgttyb *) 0);
  1009. X    sleep(1);
  1010. X    return(ioctl(fds, TIOCCBRK, (struct sgttyb *) 0));
  1011. X}
  1012. X
  1013. X/*
  1014. X * Fix the file descriptor so that a read is satisfied immediately.  When
  1015. X * read() is called it returns the character in the queue, or an error if
  1016. X * no key was pressed.
  1017. X */
  1018. X
  1019. Xint
  1020. Xtty_noblock(fds, on)
  1021. Xint fds, on;
  1022. X{
  1023. X    int current;
  1024. X
  1025. X    current = fcntl(fds, F_GETFL, 0);
  1026. X    if (on)
  1027. X        return(fcntl(fds, F_SETFL, current | FNDELAY));
  1028. X    else
  1029. X        return(fcntl(fds, F_SETFL, current & ~FNDELAY));
  1030. X}
  1031. X
  1032. X/*
  1033. X * Get the current baud rate of the terminal
  1034. X */
  1035. X
  1036. Xint
  1037. Xmy_speed()
  1038. X{
  1039. X    static int speed[15] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
  1040. X     1200, 1800, 2400, 4800, 9600, 19200};
  1041. X    struct sgttyb tbuf;
  1042. X
  1043. X    ioctl(0, TIOCGETP, &tbuf);
  1044. X    return(speed[tbuf.sg_ispeed]);
  1045. X}
  1046. SHAR_EOF
  1047. if test 4666 -ne "`wc -c < 'tty_ucb.c'`"
  1048. then
  1049.     echo shar: "error transmitting 'tty_ucb.c'" '(should have been 4666 characters)'
  1050. fi
  1051. fi
  1052. echo shar: "extracting 'vcs.c'" '(10939 characters)'
  1053. if test -f 'vcs.c'
  1054. then
  1055.     echo shar: "will not over-write existing file 'vcs.c'"
  1056. else
  1057. sed 's/^X//' << \SHAR_EOF > 'vcs.c'
  1058. X/*
  1059. X * Routines for VCS detection.
  1060. X */
  1061. X
  1062. X#include <stdio.h>
  1063. X#include "config.h"
  1064. X#include "vcs.h"
  1065. X
  1066. X#ifndef OLDCURSES
  1067. X#include <curses.h>
  1068. X#include <term.h>
  1069. X#endif /* OLDCURSES */
  1070. X
  1071. Xstatic int putc_cnt;
  1072. Xstatic char putc_buf[VCS_SIZE];
  1073. X
  1074. X/*
  1075. X * Test for possible VCS (video command sequence).  A character return
  1076. X * code means no match.  An return code greater than 255 means a VCS
  1077. X * was found.
  1078. X */
  1079. X
  1080. Xint
  1081. Xvcs_filter(c)
  1082. Xchar c;
  1083. X{
  1084. X    extern int vcs_codes[NUM_VCS][VCS_SIZE], vcs_leadin[NUM_VCS];
  1085. X    extern int num_leadin;
  1086. X    static int vcs_buf[VCS_SIZE];
  1087. X    static int ptr = 0;
  1088. X    register int i;
  1089. X    int maybe, possible;
  1090. X
  1091. X                    /* see if possible */
  1092. X    possible = 0;
  1093. X    if (ptr == 0) {
  1094. X        /*
  1095. X         * This is kinda crude... I'm checking to see if the
  1096. X         * lead-in character is greater than the space character.
  1097. X         * If so, it most probably is NOT a VCS.
  1098. X         */
  1099. X        if (c >= ' ')
  1100. X            return(c & 0xff);
  1101. X                    /* check the list */
  1102. X        for (i=0; i<num_leadin; i++) {
  1103. X            if (c == vcs_leadin[i]) {
  1104. X                possible++;
  1105. X                break;
  1106. X            }
  1107. X        }
  1108. X        if (!possible)
  1109. X            return(c & 0xff);
  1110. X    }
  1111. X
  1112. X                    /* build the string */
  1113. X    vcs_buf[ptr++] = c;
  1114. X    vcs_buf[ptr] = -1;
  1115. X                    /* test for match */
  1116. X    maybe = 0;
  1117. X    for (i=0; i<NUM_VCS; i++) {
  1118. X        switch (match_codes(vcs_buf, vcs_codes[i], i)) {
  1119. X            case YES:
  1120. X                ptr = 0;
  1121. X                return(i+256);
  1122. X            case NO:
  1123. X                break;
  1124. X            case MAYBE:
  1125. X                maybe++;
  1126. X                break;
  1127. X        }
  1128. X    }
  1129. X                    /* abandon what you've got */
  1130. X    if (maybe && ptr == VCS_SIZE-1) {
  1131. X        ptr = 0;
  1132. X        return(c & 0xff);
  1133. X    }
  1134. X                    /* hang on, wait and see */
  1135. X    if (maybe)
  1136. X        return(MAYBE);
  1137. X                    /* a clean miss */
  1138. X    ptr = 0;
  1139. X    return(c & 0xff);
  1140. X}
  1141. X
  1142. X/*
  1143. X * See if the two integer arrays "match".  Character parameters are
  1144. X * designated by codes > 1000 and ASCII digit parameters are designated
  1145. X * by codes > 2000.  Uses a simple linear search, so if NUM_VCS grows
  1146. X * this routine will have to mature a bit.
  1147. X */
  1148. X
  1149. Xstatic int
  1150. Xmatch_codes(test, code, k)
  1151. Xint test[], code[], k;
  1152. X{
  1153. X    extern int vcs_param[NUM_VCS][5];
  1154. X    register int i, j;
  1155. X    int pos, done;
  1156. X                    /* doesn't exist */
  1157. X    if (code[0] == -1)
  1158. X        return(NO);
  1159. X
  1160. X    i = 0;
  1161. X    j = 0;
  1162. X    while (i<VCS_SIZE && j<VCS_SIZE) {
  1163. X                    /* at the end (a match) */
  1164. X        if (test[i] == -1 && code[j] == -1)
  1165. X            return(YES);
  1166. X                    /* ran out of input */
  1167. X        if (test[i] == -1)
  1168. X            break;
  1169. X        /*
  1170. X         * The char parameter (code 1000) always matches the
  1171. X         * next character.
  1172. X         */
  1173. X        if (code[j] >= 1000 && code[j] < 2000) {
  1174. X            pos = code[j] -1000;
  1175. X            vcs_param[k][pos] = test[i];
  1176. X            i++;
  1177. X            j++;
  1178. X            continue;
  1179. X        }
  1180. X        /*
  1181. X         * The digit parameter (code 2000) tries to match as many
  1182. X         * ASCII digits as it can.
  1183. X         */
  1184. X        if (code[j] >= 2000) {
  1185. X            pos = code[j] -2000;
  1186. X                    /* done with this number? */
  1187. X            if (vcs_param[k][pos])
  1188. X                done = 1;
  1189. X            else
  1190. X                done = 0;
  1191. X                    /* only digits */
  1192. X            while (test[i] >= 48 && test[i] <= 57) {
  1193. X                if (!done)
  1194. X                    vcs_param[k][pos] = (vcs_param[k][pos] * 10) + test[i] -48;
  1195. X                i++;
  1196. X            }
  1197. X                    /* ended in a digit */
  1198. X            if (test[i] == -1 && code[j+1] != -1) {
  1199. X                vcs_param[k][pos] = 0;
  1200. X                break;
  1201. X            }
  1202. X            j++;
  1203. X            continue;
  1204. X        }
  1205. X                    /* a clean miss */
  1206. X        if (test[i] != code[j]) {
  1207. X            for (j=0; j<5; j++)
  1208. X                vcs_param[k][j] = 0;
  1209. X            return(NO);
  1210. X        }
  1211. X        i++;
  1212. X        j++;
  1213. X    }
  1214. X                    /* a maybe */
  1215. X    return(MAYBE);
  1216. X}
  1217. X
  1218. X/*
  1219. X * Build the table of VCS codes.  Actually we cheat... We tell curses(3)
  1220. X * to build the strings to perform the function, and then we decipher
  1221. X * what it did.
  1222. X *
  1223. X * For example: On a vt100 the cursor motion string in terminfo is:
  1224. X *    cup=\E[%i%p1%d;%p2%dH$<5>
  1225. X *
  1226. X * This gets translated to the integer array vcs_code[] as:
  1227. X *    \E   [   %p1%d  ;   %p2%d  H
  1228. X *    27,  91, 2000,  59, 2001,  72
  1229. X * 
  1230. X * Notice that the "%p1" and "%p2" parameters get translated to 2000 and
  1231. X * 2001.  This is to signify that the parameters are multiple digit ASCII
  1232. X * encoded numbers.  The "%i" and "%d" codes are imbedded into the vcs_opt[]
  1233. X * array in somewhat of a loose manner.  In other words, there is no set
  1234. X * format for the vcs_opt[] array.  The padding info "$<5>" is ignored.
  1235. X */
  1236. X
  1237. Xvoid
  1238. Xvcs_table()
  1239. X{
  1240. X    extern int vcs_codes[NUM_VCS][VCS_SIZE], vcs_opt[NUM_VCS][10];
  1241. X    extern int vcs_leadin[NUM_VCS], num_leadin, max_row, max_col;
  1242. X    int i, j, k, match, temp[VCS_SIZE];
  1243. X    char *p, *strcpy(), buf[VCS_SIZE], *getenv(), *tparm();
  1244. X    void fake_it();
  1245. X
  1246. X#ifdef OLDCURSES
  1247. X    char tcbuf[1024], tb[1024], *t, *cursor_home, *clr_eol, *clr_eos;
  1248. X    char *clear_screen, *cursor_up, *cursor_down, *cursor_right;
  1249. X    char *cursor_left, *cursor_address, *getenv(), *tgetstr(), *tgoto();
  1250. X
  1251. X    tgetent(tb, getenv("TERM"));
  1252. X    t = tcbuf;
  1253. X
  1254. X    cursor_home = tgetstr("ho", &t);
  1255. X    clr_eol = tgetstr("ce", &t);
  1256. X    clr_eos = tgetstr("cd", &t);
  1257. X    clear_screen = tgetstr("cl", &t);
  1258. X    cursor_up = tgetstr("up", &t);
  1259. X    cursor_down = tgetstr("do", &t);
  1260. X    cursor_right = tgetstr("nd", &t);
  1261. X    cursor_left = tgetstr("le", &t);
  1262. X    cursor_address = tgetstr("cm", &t);
  1263. X    max_row = tgetnum("li");
  1264. X    max_col = tgetnum("co");
  1265. X#else /* OLDCURSES */
  1266. X    setupterm(getenv("TERM"), 1, &i);
  1267. X    max_row = lines;
  1268. X    max_col = columns;
  1269. X#endif /* OLDCURSES */
  1270. X
  1271. X    /*
  1272. X     * Do the easy ones first.  These don't take positional parameters,
  1273. X     * so all we have to do is strip the padding info.
  1274. X     */
  1275. X    for (i=0; i<NUM_VCS; i++) {
  1276. X        switch (i) {
  1277. X            case HOME:
  1278. X                p = cursor_home;
  1279. X                break;
  1280. X            case CLR_EOL:
  1281. X                p = clr_eol;
  1282. X                break;
  1283. X            case CLR_EOS:
  1284. X                p = clr_eos;
  1285. X                break;
  1286. X            case CLEAR:
  1287. X                p = clear_screen;
  1288. X                break;
  1289. X            case MV_UP:
  1290. X                p = cursor_up;
  1291. X                break;
  1292. X            case MV_DOWN:
  1293. X                p = cursor_down;
  1294. X                break;
  1295. X            case MV_RIGHT:
  1296. X                p = cursor_right;
  1297. X                break;
  1298. X            case MV_LEFT:
  1299. X                p = cursor_left;
  1300. X                break;
  1301. X            default:
  1302. X                p = "";
  1303. X                break;
  1304. X        }
  1305. X        /*
  1306. X         * Either the capability doesn't exist, or we're gonna
  1307. X         * do this one by hand (i.e.: ones with positional parameters)
  1308. X         */
  1309. X        if (!p) {
  1310. X            vcs_codes[i][0] = -1;
  1311. X            continue;
  1312. X        }
  1313. X                    /* fake an "output" */
  1314. X        fake_it(p);
  1315. X                    /* copy what it did */
  1316. X        j = 0;
  1317. X        while (putc_buf[j]) {
  1318. X            vcs_codes[i][j] = putc_buf[j];
  1319. X            j++;
  1320. X            if (j == VCS_SIZE-1)
  1321. X                break;
  1322. X        }
  1323. X        vcs_codes[i][j] = -1;
  1324. X    }
  1325. X
  1326. X    /*
  1327. X     * And now for the difficult ones.  The way it's done is: load the
  1328. X     * string with a few known parameters and then find where the
  1329. X     * parameters end up.  The vcs_opt[][] array is "free-flowing"
  1330. X     * and means something only to the routine being used.
  1331. X     */
  1332. X                    /* add one to the param */
  1333. X    if (substr(cursor_address, "%i") > 0)
  1334. X        vcs_opt[MV_DIRECT][0] = 1;
  1335. X                    /* decimal codes used */
  1336. X    if (substr(cursor_address, "%d") > 0)
  1337. X        vcs_opt[MV_DIRECT][1] = 1;
  1338. X                    /* character codes used */
  1339. X    if (substr(cursor_address, "%c") > 0)
  1340. X        vcs_opt[MV_DIRECT][2] = 1;
  1341. X                    /* add an offset */
  1342. X    if (substr(cursor_address, "%+") > 0)
  1343. X        vcs_opt[MV_DIRECT][3] = 1;
  1344. X                    /* subtract an offset */
  1345. X    if (substr(cursor_address, "%-") > 0)
  1346. X        vcs_opt[MV_DIRECT][4] = 1;
  1347. X                    /* load with parameters 12 & 34 */
  1348. X#ifdef OLDCURSES
  1349. X    fake_it(tgoto(cursor_address, 12, 34));
  1350. X#else /* OLDCURSES */
  1351. X    fake_it(tparm(cursor_address, 12, 34));
  1352. X#endif /* OLDCURSES */
  1353. X
  1354. X    j = 0;
  1355. X    while (putc_buf[j]) {
  1356. X        temp[j] = putc_buf[j];
  1357. X        j++;
  1358. X        if (j == VCS_SIZE-1)
  1359. X            break;
  1360. X    }
  1361. X    temp[j] = -1;
  1362. X                    /* if decimal parameters */
  1363. X    if (vcs_opt[MV_DIRECT][1]) {
  1364. X                    /* if add one */
  1365. X        if (vcs_opt[MV_DIRECT][0])
  1366. X            strcpy(buf, "13");
  1367. X        else
  1368. X            strcpy(buf, "12");
  1369. X                    /* where is the 12 (or 13)? */
  1370. X        if ((i = substr(putc_buf, buf)) > 0) {
  1371. X            temp[i] = 2000;
  1372. X            temp[i+1] = -2;
  1373. X        }
  1374. X        else
  1375. X            temp[0] = -1;
  1376. X                    /* if add one */
  1377. X        if (vcs_opt[MV_DIRECT][0])
  1378. X            strcpy(buf, "35");
  1379. X        else
  1380. X            strcpy(buf, "34");
  1381. X                    /* where is the 34 (or 35)? */
  1382. X        if ((i = substr(putc_buf, buf)) > 0) {
  1383. X            temp[i] = 2001;
  1384. X            temp[i+1] = -2;
  1385. X        }
  1386. X        else
  1387. X            temp[0] = -1;
  1388. X    }
  1389. X                    /* if character parameters */
  1390. X    if (vcs_opt[MV_DIRECT][2]) {
  1391. X                    /* original with 12 and 34 */
  1392. X        strcpy(buf, putc_buf);
  1393. X                    /* change 12 to 13 */
  1394. X#ifdef OLDCURSES
  1395. X        fake_it(tgoto(cursor_address, 13, 34));
  1396. X#else /* OLDCURSES */
  1397. X        fake_it(tparm(cursor_address, 13, 34));
  1398. X#endif /* OLDCURSES */
  1399. X                    /* where are they different */
  1400. X        i = 0;
  1401. X        while (buf[i] != '\0') {
  1402. X            if (buf[i] != putc_buf[i])
  1403. X                break;
  1404. X            i++;
  1405. X        }
  1406. X                    /* sanity checking */
  1407. X        if (buf[i] == '\0')
  1408. X            temp[0] = -1;
  1409. X                    /* if add, what is offset? */
  1410. X        if (vcs_opt[MV_DIRECT][3])
  1411. X            vcs_opt[MV_DIRECT][5] = temp[i] - 13;
  1412. X
  1413. X                    /* if subtract, what is offset? */
  1414. X        if (vcs_opt[MV_DIRECT][4])
  1415. X            vcs_opt[MV_DIRECT][5] = 13 - temp[i];
  1416. X
  1417. X        temp[i] = 1000;
  1418. X                    /* change 34 to 35 */
  1419. X#ifdef OLDCURSES
  1420. X        fake_it(tgoto(cursor_address, 12, 35));
  1421. X#else /* OLDCURSES */
  1422. X        fake_it(tparm(cursor_address, 12, 35));
  1423. X#endif /* OLDCURSES */
  1424. X                    /* where are they different */
  1425. X        i = 0;
  1426. X        while (buf[i] != '\0') {
  1427. X            if (buf[i] != putc_buf[i])
  1428. X                break;
  1429. X            i++;
  1430. X        }
  1431. X        temp[i] = 1001;
  1432. X        if (buf[i] == '\0')
  1433. X            temp[0] = -1;
  1434. X    }
  1435. X                    /* strip the -2's out, if any */
  1436. X    i = 0;
  1437. X    j = 0;
  1438. X    while (temp[i] != -1) {
  1439. X        if (temp[i] != -2)
  1440. X            vcs_codes[MV_DIRECT][j++] = temp[i];
  1441. X        i++;
  1442. X    }
  1443. X    vcs_codes[MV_DIRECT][j] = -1;
  1444. X
  1445. X    /*
  1446. X     * Simplify the list.  Some codes are already handled by the
  1447. X     * virtual screen routines... no need to duplicate them.
  1448. X     */
  1449. X    if (vcs_codes[MV_DOWN][0] == '\n')
  1450. X        vcs_codes[MV_DOWN][0] = -1;
  1451. X
  1452. X    if (vcs_codes[MV_LEFT][0] == 8)
  1453. X        vcs_codes[MV_LEFT][0] = -1;
  1454. X
  1455. X    /*
  1456. X     * Often the "clear screen" sequence will contain the "home"
  1457. X     * sequence... if so, don't duplicate the "home" portion.
  1458. X     */
  1459. X    fake_it(cursor_home);
  1460. X    strcpy(buf, putc_buf);
  1461. X
  1462. X    fake_it(clear_screen);
  1463. X                    /* if "home" inside "clear screen" */
  1464. X    if ((k = substr(putc_buf, buf)) >= 0) {
  1465. X                    /* if at the beginning */
  1466. X        if (k == 0) {
  1467. X            i = 0;
  1468. X            for (j=strlen(buf); j<VCS_SIZE; j++)
  1469. X                vcs_codes[CLEAR][i++] = putc_buf[j];
  1470. X            vcs_codes[CLEAR][i] = -1;
  1471. X        }
  1472. X                    /* if at the end */
  1473. X        else if (strlen(buf)+k == strlen(putc_buf))
  1474. X            vcs_codes[CLEAR][k] = -1;
  1475. X    }
  1476. X                    /* is "clear screen" still unique */
  1477. X    k = 0;
  1478. X    for (i=0; i<NUM_VCS; i++) {
  1479. X        if (vcs_codes[CLEAR][i] == -1 || vcs_codes[CLR_EOS][i] == -1)
  1480. X            break;
  1481. X        if (vcs_codes[CLEAR][i] != vcs_codes[CLR_EOS][i]) {
  1482. X            k++;
  1483. X            break;
  1484. X        }
  1485. X    }
  1486. X    if (k == 0)
  1487. X        vcs_codes[CLEAR][0] = -1;
  1488. X
  1489. X    /*
  1490. X     * Make a list of unique lead-in characters to be used as a
  1491. X     * simple hash table.
  1492. X     */
  1493. X    num_leadin = 0;
  1494. X    for (i=0; i<NUM_VCS; i++) {
  1495. X        if (vcs_codes[i][0] == -1)
  1496. X            continue;
  1497. X                    /* add any new lead-in character */
  1498. X        match = 0;
  1499. X        for (j=0; j<num_leadin; j++) {
  1500. X            if (vcs_leadin[j] == vcs_codes[i][0])
  1501. X                match++;
  1502. X        }
  1503. X        if (!match)
  1504. X            vcs_leadin[num_leadin++] = vcs_codes[i][0];
  1505. X    }
  1506. X    return;
  1507. X}
  1508. X
  1509. X/*
  1510. X * The routine that fakes curses(3) into outputting the string info with
  1511. X * the padding removed.
  1512. X */
  1513. Xstatic void
  1514. Xfake_it(s)
  1515. Xchar *s;
  1516. X{
  1517. X    int fake_putc();
  1518. X
  1519. X    putc_cnt = 0;
  1520. X    putc_buf[0] = '\0';
  1521. X    tputs(s, 1, fake_putc);
  1522. X    putc_buf[putc_cnt] = '\0';
  1523. X    return;
  1524. X}
  1525. Xstatic int
  1526. Xfake_putc(c)
  1527. Xchar c;
  1528. X{
  1529. X    if (c != '\0')
  1530. X        putc_buf[putc_cnt++] = c;
  1531. X    return(c);
  1532. X}
  1533. X
  1534. X/*
  1535. X * Is string2 contained in string1?  If so, return the offset, otherwise
  1536. X * return a -1.
  1537. X */
  1538. X
  1539. Xstatic int
  1540. Xsubstr(s1, s2)
  1541. Xchar *s1, *s2;
  1542. X{
  1543. X    int i, len;
  1544. X
  1545. X    len = strlen(s2);
  1546. X                    /* not possible */
  1547. X    if (len > strlen(s1))
  1548. X        return(-1);
  1549. X
  1550. X    i = 0;
  1551. X    while (*s1) {
  1552. X        if (!strncmp(s1, s2, len))
  1553. X            return(i);
  1554. X        s1++;
  1555. X        i++;
  1556. X    }
  1557. X    return(-1);
  1558. X}
  1559. SHAR_EOF
  1560. if test 10939 -ne "`wc -c < 'vcs.c'`"
  1561. then
  1562.     echo shar: "error transmitting 'vcs.c'" '(should have been 10939 characters)'
  1563. fi
  1564. fi
  1565. echo shar: "extracting 'vcs.h'" '(330 characters)'
  1566. if test -f 'vcs.h'
  1567. then
  1568.     echo shar: "will not over-write existing file 'vcs.h'"
  1569. else
  1570. sed 's/^X//' << \SHAR_EOF > 'vcs.h'
  1571. X/*
  1572. X * Definitions to support the detection of video command sequences
  1573. X */
  1574. X
  1575. X#define VCS_SIZE    25
  1576. X#define NUM_VCS        9
  1577. X
  1578. X#define HOME        0
  1579. X#define CLR_EOL        1
  1580. X#define CLR_EOS        2
  1581. X#define CLEAR        3
  1582. X#define MV_UP        4
  1583. X#define MV_DOWN        5
  1584. X#define MV_RIGHT    6
  1585. X#define MV_LEFT        7
  1586. X#define MV_DIRECT    8
  1587. X
  1588. X#define YES        1
  1589. X#define NO        0
  1590. X#define MAYBE        (-1)
  1591. SHAR_EOF
  1592. if test 330 -ne "`wc -c < 'vcs.h'`"
  1593. then
  1594.     echo shar: "error transmitting 'vcs.h'" '(should have been 330 characters)'
  1595. fi
  1596. fi
  1597. echo shar: "extracting 'waitfor.c'" '(2108 characters)'
  1598. if test -f 'waitfor.c'
  1599. then
  1600.     echo shar: "will not over-write existing file 'waitfor.c'"
  1601. else
  1602. sed 's/^X//' << \SHAR_EOF > 'waitfor.c'
  1603. X/*
  1604. X * Wait for a string on the stdin.  Returns a 0 on success, 1 on failure
  1605. X * and -1 on error.  This is an external program designed to be used in
  1606. X * shell scripts.
  1607. X */
  1608. X
  1609. X#define TIMEOUT    10
  1610. X#define BUF_SIZ    1024
  1611. X#define HZ    60
  1612. X#define STRSTR
  1613. X
  1614. Xint wf_flag;
  1615. X
  1616. X#include <stdio.h>
  1617. X#include <signal.h>
  1618. X#include <sys/types.h>
  1619. X#include <sys/times.h>
  1620. X
  1621. X#ifdef BSD
  1622. X#include <setjmp.h>
  1623. Xjmp_buf wf_buf;
  1624. X#endif /* BSD */
  1625. X
  1626. Xmain(argc, argv)
  1627. Xint argc;
  1628. Xchar *argv[];
  1629. X{
  1630. X    int i, j, timeout;
  1631. X    char c, buf[BUF_SIZ], *string, *strstr();
  1632. X    struct tms t;
  1633. X    long t1;
  1634. X    void exit();
  1635. X
  1636. X    if (argc < 2 || argc > 3) {
  1637. X        fprintf(stderr, "Usage: waitfor -n string\n");
  1638. X        exit(-1);
  1639. X    }
  1640. X
  1641. X    if (argv[1][0] == '-') {
  1642. X        timeout = atoi(&argv[1][1]);
  1643. X        if (argc != 3) {
  1644. X            fprintf(stderr, "Usage: waitfor -n string\n");
  1645. X            exit(-1);
  1646. X        }
  1647. X        string = argv[2];
  1648. X    }
  1649. X    else {
  1650. X        timeout = TIMEOUT;
  1651. X        string = argv[1];
  1652. X    }
  1653. X                    /* here we go.. */
  1654. X    i = 0;
  1655. X    t1 = times(&t);
  1656. X    while ((times(&t) - t1) < (HZ * timeout)) {
  1657. X        if ((j = getc_line()) != -1) {
  1658. X            c = j & 0x7f;
  1659. X                    /* no NULLs please */
  1660. X            if (c != '\0') {
  1661. X                buf[i++] = c;
  1662. X                buf[i] = '\0';
  1663. X            }
  1664. X
  1665. X            if (i >= BUF_SIZ) {
  1666. X                fprintf(stderr, "waitfor: buffer overflow\n");
  1667. X                exit(-1);
  1668. X            }
  1669. X                    /* yea.. we found it! */
  1670. X            if (strstr(buf, string))
  1671. X                exit(0);
  1672. X        }
  1673. X    }
  1674. X    exit(1);
  1675. X}
  1676. X
  1677. Xint
  1678. Xgetc_line()
  1679. X{
  1680. X    int wf_force();
  1681. X    char c;
  1682. X    unsigned int alarm();
  1683. X
  1684. X    signal(SIGALRM, wf_force);
  1685. X    wf_flag = 0;
  1686. X
  1687. X    alarm(1);
  1688. X
  1689. X#ifdef BSD
  1690. X    if (setjmp(wf_buf))
  1691. X        return(-1);
  1692. X#endif /* BSD */
  1693. X
  1694. X    if (read(0, &c, 1) <= 0) {
  1695. X        alarm(0);
  1696. X        return(-1);
  1697. X    }
  1698. X    if (wf_flag)
  1699. X        return(-1);
  1700. X    alarm(0);
  1701. X    return(c & 0xff);
  1702. X}
  1703. X
  1704. X/* ARGSUSED */
  1705. Xstatic int
  1706. Xwf_force(dummy)
  1707. Xint dummy;
  1708. X{
  1709. X#ifdef BSD
  1710. X    longjmp(wf_buf, 1);
  1711. X#else /* BSD */
  1712. X    signal(SIGALRM, wf_force);
  1713. X    wf_flag = 1;
  1714. X#endif /* BSD */
  1715. X}
  1716. X
  1717. X#ifdef STRSTR
  1718. X/*
  1719. X * Return a pointer to the first occurance of string str2 in str1.
  1720. X * Returns a NULL if str2 is not in str1.
  1721. X */
  1722. X
  1723. Xchar *
  1724. Xstrstr(str1, str2)
  1725. Xchar *str1, *str2;
  1726. X{
  1727. X    int len;
  1728. X    len = strlen(str2);
  1729. X    while (*str1) {
  1730. X        if (*str2 == *str1) {
  1731. X            if (!strncmp(str2, str1, len))
  1732. X                return(str1);
  1733. X        }
  1734. X        str1++;
  1735. X    }
  1736. X    return(NULL);
  1737. X}
  1738. X#endif /* STRSTR */
  1739. SHAR_EOF
  1740. if test 2108 -ne "`wc -c < 'waitfor.c'`"
  1741. then
  1742.     echo shar: "error transmitting 'waitfor.c'" '(should have been 2108 characters)'
  1743. fi
  1744. fi
  1745. echo shar: "extracting 'x_ascii.c'" '(6450 characters)'
  1746. if test -f 'x_ascii.c'
  1747. then
  1748.     echo shar: "will not over-write existing file 'x_ascii.c'"
  1749. else
  1750. sed 's/^X//' << \SHAR_EOF > 'x_ascii.c'
  1751. X/*
  1752. X * Transfer a file using just XON/XOFF flow control.  Currently limited to
  1753. X * 7 bit ASCII codes.  (If this causes too much trouble, I'll change it).
  1754. X */
  1755. X
  1756. X#include <stdio.h>
  1757. X#include <curses.h>
  1758. X#include <signal.h>
  1759. X#include "config.h"
  1760. X#include "misc.h"
  1761. X#include "param.h"
  1762. X
  1763. X#ifdef BSD
  1764. X#include <setjmp.h>
  1765. Xjmp_buf bl_buf;
  1766. X#endif /* BSD */
  1767. X
  1768. Xvoid
  1769. Xxfer_ascii(list, up)
  1770. Xchar *list;
  1771. Xint up;
  1772. X{
  1773. X    int cr_lf;
  1774. X    char *file, *strtok();
  1775. X    void send_ascii(), rcv_ascii(), line_set(), st_line(), suspend();
  1776. X    void load_vs(), ascii_mode(), input_off(), term_mode();
  1777. X    unsigned int sleep();
  1778. X
  1779. X    touchwin(stdscr);
  1780. X    refresh();
  1781. X                    /* only one file from list */
  1782. X    file = strtok(list, " \t");
  1783. X
  1784. X    cr_lf = !strcmp(param->cr_out, "CR/LF");
  1785. X    ascii_mode(up);
  1786. X                    /* out of curses mode */
  1787. X    resetterm();
  1788. X    term_mode();
  1789. X    tty_noblock(0, TRUE);
  1790. X
  1791. X    if (up) {
  1792. X                    /* un-suspend the input routine */
  1793. X        suspend(FALSE);
  1794. X        send_ascii(file, cr_lf);
  1795. X        suspend(TRUE);
  1796. X    }
  1797. X    else {
  1798. X        input_off();
  1799. X        rcv_ascii(file, cr_lf);
  1800. X    }
  1801. X
  1802. X    /*
  1803. X     * Restoring the TTY modes is easier than setting them... The
  1804. X     * fixterm() and line_set() routines fix most of the damage.
  1805. X     */
  1806. X    line_set();
  1807. X    fixterm();
  1808. X    tty_noblock(0, FALSE);
  1809. X
  1810. X    /*
  1811. X     * On downloading, the contents of the virtual screen won't contain
  1812. X     * the characters shown during the transfer.  Too bad...
  1813. X     */
  1814. X    load_vs();
  1815. X    beep();
  1816. X    st_line("xfer complete");
  1817. X
  1818. X    sleep(2);
  1819. X    return;
  1820. X}
  1821. X
  1822. X/*
  1823. X * Send a file.  The local echo option is independent of the duplex option,
  1824. X * and would very rarely be used since the characters are most likely
  1825. X * being echoed on the screen anyway.
  1826. X */
  1827. X
  1828. Xstatic void
  1829. Xsend_ascii(file, cr_lf)
  1830. Xchar *file;
  1831. Xint cr_lf;
  1832. X{
  1833. X    extern int fd;
  1834. X    FILE *fp, *my_fopen();
  1835. X    int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, lecho, pace;
  1836. X    char buf[80];
  1837. X    unsigned char c, last;
  1838. X    unsigned int sleep();
  1839. X    void error_win();
  1840. X                    /* permission already checked */
  1841. X    if (!(fp = my_fopen(file, "r"))) {
  1842. X        sprintf(buf, "\"%s\"", file);
  1843. X        error_win(0, "Can't open file for read", buf);
  1844. X        return;
  1845. X    }
  1846. X                    /* ASCII transfer options */
  1847. X    strip_cr = !strcmp(param->cr_up, "STRIP");
  1848. X    add_lf = !strcmp(param->cr_up, "ADD LF");
  1849. X    strip_lf = !strcmp(param->lf_up, "STRIP");
  1850. X    add_cr = !strcmp(param->lf_up, "ADD CR");
  1851. X    expand = !strcmp(param->expand, "YES");
  1852. X    lecho = !strcmp(param->lecho, "YES");
  1853. X    pace = !strcmp(param->pace, "YES");
  1854. X
  1855. X    last = 0;
  1856. X    while ((i = fgetc(fp)) != EOF) {
  1857. X                    /* any keyboard activity? */
  1858. X        switch (j = getchar()) {
  1859. X            case -1:    /* no key was pressed */
  1860. X                break;
  1861. X            case ESC:    /* <ESC> key for abort */
  1862. X                fclose(fp);
  1863. X                sleep(2);
  1864. X                tty_drain(fd);
  1865. X                return;
  1866. X            default:    /* send the char */
  1867. X                c = j;
  1868. X                putc_line(c);
  1869. X                if (c == '\r' && cr_lf)
  1870. X                    putc_line('\n');
  1871. X                break;
  1872. X        }
  1873. X        c = i & 0x7f;
  1874. X                    /* expand blank lines */
  1875. X        if (expand && last == '\n' && c == '\n')
  1876. X            putc_line(' ');
  1877. X        last = c;
  1878. X
  1879. X                    /* CR translations */
  1880. X        if (c == '\r' && strip_cr)
  1881. X            continue;
  1882. X        if (c == '\r' && add_lf) {
  1883. X            putc_line(c);
  1884. X            putc_line('\n');
  1885. X            continue;
  1886. X        }
  1887. X                    /* LF translations */
  1888. X        if (c == '\n' && strip_lf)
  1889. X            continue;
  1890. X        if (c == '\n' && add_cr) {
  1891. X            putc_line('\r');
  1892. X            putc_line(c);
  1893. X            continue;
  1894. X        }
  1895. X        putc_line(c);
  1896. X        /*
  1897. X         * There's really no mechanism for delaying characters
  1898. X         * going to the output, so we fake it by waiting for
  1899. X         * each character to clear the I/O buffer.
  1900. X         */
  1901. X        if (pace)
  1902. X            tty_drain(fd);
  1903. X        if (lecho) {
  1904. X            putchar((char) c);
  1905. X            fflush(stdout);
  1906. X        }
  1907. X    }
  1908. X    fclose(fp);
  1909. X    sleep(2);
  1910. X    tty_drain(fd);
  1911. X    return;
  1912. X}
  1913. X
  1914. X/*
  1915. X * Receive a file.  The timer is used to end the transfer.  This is not
  1916. X * that much different from the data logging option.  The use of bgetc_line()
  1917. X * and non-blocking input makes it seem like full duplex, but it's not.
  1918. X * Be aware that while the timer is active the keyboard is deaf.  Input is
  1919. X * NOT loaded into the virtual screen!!
  1920. X */
  1921. X
  1922. Xstatic void
  1923. Xrcv_ascii(file, cr_lf)
  1924. Xchar *file;
  1925. Xint cr_lf;
  1926. X{
  1927. X    FILE *fp, *my_fopen();
  1928. X    int i, strip_cr, strip_lf, add_cr, add_lf, got_first;
  1929. X    unsigned int delay;
  1930. X    char c, buf[80];
  1931. X    void error_win();
  1932. X                    /* permission already checked */
  1933. X    if (!(fp = my_fopen(file, "w"))) {
  1934. X        sprintf(buf, "\"%s\"", file);
  1935. X        error_win(0, "Can't open file for write", buf);
  1936. X        return;
  1937. X    }
  1938. X                    /* ASCII transfer options */
  1939. X    strip_cr = !strcmp(param->cr_dn, "STRIP");
  1940. X    add_lf = !strcmp(param->cr_dn, "ADD LF");
  1941. X    strip_lf = !strcmp(param->lf_dn, "STRIP");
  1942. X    add_cr = !strcmp(param->lf_dn, "ADD CR");
  1943. X
  1944. X    got_first = 0;
  1945. X    delay = 1;
  1946. X    while (1) {
  1947. X                    /* keyboard activity */
  1948. X        switch (i = getchar()) {
  1949. X            case -1:    /* no key was pressed */
  1950. X                break;
  1951. X            case ESC:    /* <ESC> key */
  1952. X                fclose(fp);
  1953. X                return;
  1954. X            default:    /* send it */
  1955. X                c = i;
  1956. X                putc_line((unsigned char) c);
  1957. X                if (c == '\r' && cr_lf)
  1958. X                    putc_line('\n');
  1959. X                break;
  1960. X        }
  1961. X                    /* read a character */
  1962. X        if ((i = bgetc_line(delay)) == -1) {
  1963. X            /*
  1964. X             * The transfer timeout is not activated until the
  1965. X             * first character is received.  Until then, it polls
  1966. X             * the line for one second and loops backs for
  1967. X             * keyboard input.
  1968. X             */
  1969. X            if (got_first) {
  1970. X                fclose(fp);
  1971. X                return;
  1972. X            }
  1973. X            continue;
  1974. X        }
  1975. X        got_first = 1;
  1976. X        delay = param->timer;
  1977. X        c = i & 0x7f;
  1978. X                    /* display it on the screen */
  1979. X        putchar(c);
  1980. X        fflush(stdout);
  1981. X                    /* CR translations */
  1982. X        if (c == '\r' && strip_cr)
  1983. X            continue;
  1984. X        if (c == '\r' && add_lf) {
  1985. X            fputc(c, fp);
  1986. X            fputc('\n', fp);
  1987. X            continue;
  1988. X        }
  1989. X                    /* LF translations */
  1990. X        if (c == '\n' && strip_lf)
  1991. X            continue;
  1992. X        if (c == '\n' && add_cr) {
  1993. X            fputc('\r', fp);
  1994. X            fputc(c, fp);
  1995. X            continue;
  1996. X        }
  1997. X        fputc(c, fp);
  1998. X    }
  1999. X}
  2000. X
  2001. X/*
  2002. X * Get a character from the line (using buffered I/O) with a specified
  2003. X * time-out period in seconds.  If the function times-out, it returns a -1.
  2004. X */
  2005. X
  2006. Xstatic int bl_flag;
  2007. X
  2008. Xstatic int
  2009. Xbgetc_line(sec)
  2010. Xunsigned int sec;
  2011. X{
  2012. X    int c, bl_force();
  2013. X    unsigned int alarm();
  2014. X
  2015. X    signal(SIGALRM, bl_force);
  2016. X    bl_flag = 0;
  2017. X
  2018. X    alarm(sec);
  2019. X
  2020. X#ifdef BSD
  2021. X    if (setjmp(bl_buf))
  2022. X        return(-1);
  2023. X#endif /* BSD */
  2024. X
  2025. X    if ((c = buf_read()) < 0) {
  2026. X        alarm(0);
  2027. X        return(-1);
  2028. X    }
  2029. X    if (bl_flag)
  2030. X        return(-1);
  2031. X    alarm(0);
  2032. X    return(c);
  2033. X}
  2034. X
  2035. X/* ARGSUSED */
  2036. Xstatic int
  2037. Xbl_force(dummy)
  2038. Xint dummy;
  2039. X{
  2040. X#ifdef BSD
  2041. X    longjmp(bl_buf, 1);
  2042. X#else /* BSD */
  2043. X    signal(SIGALRM, bl_force);
  2044. X    bl_flag = 1;
  2045. X#endif /* BSD */
  2046. X}
  2047. X
  2048. X/*
  2049. X * Do a single character buffered read from the serial port.
  2050. X */
  2051. X
  2052. Xstatic int
  2053. Xbuf_read()
  2054. X{
  2055. X    extern int fd;
  2056. X    static char buf[CLIST_SIZ];
  2057. X    static char *bufp = buf;
  2058. X    static int n = 0;
  2059. X
  2060. X    if (n <= 0) {
  2061. X        n = read(fd, buf, CLIST_SIZ);
  2062. X        bufp = buf;
  2063. X    }
  2064. X    if (--n >= 0)
  2065. X        return(*bufp++ & 0xff);
  2066. X    return(-1);
  2067. X}
  2068. SHAR_EOF
  2069. if test 6450 -ne "`wc -c < 'x_ascii.c'`"
  2070. then
  2071.     echo shar: "error transmitting 'x_ascii.c'" '(should have been 6450 characters)'
  2072. fi
  2073. fi
  2074. echo shar: "extracting 'x_batch.c'" '(8686 characters)'
  2075. if test -f 'x_batch.c'
  2076. then
  2077.     echo shar: "will not over-write existing file 'x_batch.c'"
  2078. else
  2079. sed 's/^X//' << \SHAR_EOF > 'x_batch.c'
  2080. X/*
  2081. X * Routines to support the batch protocols.
  2082. X */
  2083. X
  2084. X#include <stdio.h>
  2085. X#include <ctype.h>
  2086. X#include <curses.h>
  2087. X#include "config.h"
  2088. X#include "misc.h"
  2089. X#include "xmodem.h"
  2090. X
  2091. X/*
  2092. X * Send the file name for the modem7 batch.  Only uses 11 characters
  2093. X * of the filename.  Returns zero on success or the standard error codes.
  2094. X */
  2095. X
  2096. Xint
  2097. Xsend_modem7(win, name)
  2098. XWINDOW *win;
  2099. Xchar *name;
  2100. X{
  2101. X    char *new_name, *fix_name();
  2102. X    unsigned char sum, calc_sum();
  2103. X
  2104. X                    /* convert to 11 character name */
  2105. X    new_name = fix_name(name);
  2106. X    sum = calc_sum((unsigned char *) new_name, 12);
  2107. X
  2108. X    putc_line(ACK);
  2109. X                    /* for each character in the name */
  2110. X    while (*new_name != CTRLZ) {
  2111. X        putc_line((unsigned char) *new_name);
  2112. X
  2113. X        switch (getc_line(3)) {
  2114. X            case -1:    /* timed out */
  2115. X                clear_line(win, 12, 24, TRUE);
  2116. X                waddstr(win, "NO RESPONSE");
  2117. X                wrefresh(win);
  2118. X                return(ERROR);
  2119. X            case ACK:    /* got it! */
  2120. X                break;
  2121. X            case CAN:    /* cancel transmission */
  2122. X                if (getc_line(2) == CAN) {
  2123. X                    beep();
  2124. X                    clear_line(win, 12, 24, TRUE);
  2125. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  2126. X                    wrefresh(win);
  2127. X                    return(CANCEL);
  2128. X                }
  2129. X                /* fall thru... */
  2130. X            default:
  2131. X                clear_line(win, 12, 24, TRUE);
  2132. X                waddstr(win, "NAME FAILED");
  2133. X                wrefresh(win);
  2134. X                return(ERROR);
  2135. X        }
  2136. X        new_name++;
  2137. X    }
  2138. X    putc_line(CTRLZ);
  2139. X                    /* verify the checksum */
  2140. X    if (getc_line(10) != sum) {
  2141. X        putc_line('u');
  2142. X        clear_line(win, 12, 24, TRUE);
  2143. X        waddstr(win, "CHECKSUM FAILED");
  2144. X        wrefresh(win);
  2145. X        return(ERROR);
  2146. X    }
  2147. X    putc_line(ACK);
  2148. X    return(0);
  2149. X}
  2150. X
  2151. X/*
  2152. X * Receive a modem7 file name.  Returns zero on success, the standard error
  2153. X * codes, or a -1 on the end-of-batch.  (Oddly enough, the end-of-batch code
  2154. X * is the same as the code for a user abort)
  2155. X */
  2156. X
  2157. Xint
  2158. Xrcv_modem7(win, default_err)
  2159. XWINDOW *win;
  2160. Xint default_err;
  2161. X{
  2162. X    extern char file_name[15];
  2163. X    int i, j, err_method, err_count, got_it;
  2164. X    unsigned char sum, calc_sum();
  2165. X    char temp_name[13];
  2166. X    void change_name(), unfix_name();
  2167. X
  2168. X    err_method = default_err;
  2169. X    if (default_err == CRC_CHECKSUM)
  2170. X        err_method = CRC;
  2171. X
  2172. X    err_count = 0;
  2173. X    got_it = 0;
  2174. X    while (err_count < MAX_ERRORS) {
  2175. X                    /* switch to checksum? */
  2176. X        if (default_err == CRC_CHECKSUM && err_count > MAX_ERRORS/2)
  2177. X            err_method = CHECKSUM;
  2178. X
  2179. X        if (err_method == CRC)
  2180. X            putc_line('C');
  2181. X        else
  2182. X            putc_line(NAK);
  2183. X                    /* what'd we get? */
  2184. X        switch (getc_line(10)) {
  2185. X            case -1:    /* timed out */
  2186. X                clear_line(win, 12, 24, TRUE);
  2187. X                wattrstr(win, A_BOLD, "NO RESPONSE");
  2188. X                wrefresh(win);
  2189. X                err_count++;
  2190. X            case ACK:    /* ready to go... */
  2191. X                got_it++;
  2192. X                break;
  2193. X            default:    /* huh? */
  2194. X                clear_line(win, 12, 24, TRUE);
  2195. X                wattrstr(win, A_BOLD, "BAD HEADER");
  2196. X                wrefresh(win);
  2197. X                err_count++;
  2198. X        }
  2199. X    }
  2200. X    if (!got_it)
  2201. X        return(ERROR);
  2202. X                    /* get the name */
  2203. X    for (i=0; i<12; i++) {
  2204. X        j = getc_line(3);
  2205. X
  2206. X        switch (j) {
  2207. X            case -1:    /* timed out */
  2208. X                clear_line(win, 12, 24, TRUE);
  2209. X                wattrstr(win, A_BOLD, "NO RESPONSE");
  2210. X                wrefresh(win);
  2211. X                return(ERROR);
  2212. X            case EOT:    /* end of batch? */
  2213. X                return(-1);
  2214. X            case CAN:    /* cancel transmission */
  2215. X                if (getc_line(2) == CAN) {
  2216. X                    beep();
  2217. X                    clear_line(win, 12, 24, TRUE);
  2218. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  2219. X                    wrefresh(win);
  2220. X                    return(CANCEL);
  2221. X                }
  2222. X                /* fall thru... */
  2223. X            case 'u':    /* bad name character */
  2224. X                beep();
  2225. X                clear_line(win, 12, 24, TRUE);
  2226. X                wattrstr(win, A_BOLD, "BAD NAME");
  2227. X                wrefresh(win);
  2228. X                return(ERROR);
  2229. X            default:    /* the name... */
  2230. X                temp_name[i] = j & 0xff;
  2231. X                if (j != CTRLZ)
  2232. X                    putc_line(ACK);
  2233. X                break;
  2234. X        }
  2235. X    }
  2236. X    temp_name[12] = '\0';
  2237. X                    /* send our checksum */
  2238. X    sum = calc_sum((unsigned char *) temp_name, 12);
  2239. X    putc_line(sum);
  2240. X                    /* do they agree? */
  2241. X    if (getc_line(10) != ACK) {
  2242. X        beep();
  2243. X        clear_line(win, 12, 24, TRUE);
  2244. X        wattrstr(win, A_BOLD, "BAD NAME");
  2245. X        wrefresh(win);
  2246. X        return(ERROR);
  2247. X    }
  2248. X                    /* load the file_name array */
  2249. X    unfix_name(temp_name);
  2250. X                    /* any name collisions? */
  2251. X    change_name(win, file_name);
  2252. X    return(0);
  2253. X}
  2254. X
  2255. X/*
  2256. X * Send the block 0 information for a ymodem batch transfer.  Uses only
  2257. X * the name component of the path and the file size.
  2258. X */
  2259. X
  2260. Xint
  2261. Xsend_ymodem(win, file, size)
  2262. XWINDOW *win;
  2263. Xchar *file;
  2264. Xlong size;
  2265. X{
  2266. X    unsigned short crc, calc_crc();
  2267. X    char *strcpy(), *memset();
  2268. X    unsigned char buf[133];
  2269. X                    /* start with a clean block */
  2270. X    memset(buf, '\0', 133);
  2271. X                    /* the header */
  2272. X    buf[0] = SOH;
  2273. X    buf[1] = 0;
  2274. X    buf[2] = 255;
  2275. X
  2276. X    /*
  2277. X     * The block zero consists of the file name (no path component),
  2278. X     * a NULL, and the file length (as a string).  The end of batch
  2279. X     * marker is an empty block.
  2280. X     */
  2281. X    if (*file != '\0') {
  2282. X        strcpy((char *) &buf[3], file);
  2283. X        sprintf((char *) &buf[strlen(file)+4], "%ld", size);
  2284. X    }
  2285. X                    /* the crc */
  2286. X    crc = calc_crc(&buf[3], 128);
  2287. X    buf[131] = crc >> 8;
  2288. X    buf[132] = crc;
  2289. X                    /* the block count */
  2290. X    mvwaddstr(win, 7, 24, "0   ");
  2291. X
  2292. X    return(send_block(win, buf, 133));
  2293. X}
  2294. X
  2295. X/*
  2296. X * Receive the block 0 information for a ymodem batch transfer.  We
  2297. X * only use the file name and the size (if present).  Currently doesn't
  2298. X * support full path names.
  2299. X */
  2300. X
  2301. Xint
  2302. Xrcv_ymodem(win)
  2303. XWINDOW *win;
  2304. X{
  2305. X    extern unsigned char buf[1029];
  2306. X    extern long file_length;
  2307. X    extern char file_name[15];
  2308. X    int code, length_is_at;
  2309. X    long atol();
  2310. X
  2311. X    file_length = 0L;
  2312. X    file_name[0] = '\0';
  2313. X                    /* read the zero block */
  2314. X    if (code = rcv_block(win, 1, 1024, 0))
  2315. X        return(code);
  2316. X                    /* at end of batch */
  2317. X    if (buf[3] == '\0')
  2318. X        return(0);
  2319. X                    /* get the file name */
  2320. X    change_name(win, (char *) &buf[3]);
  2321. X                    /* any trouble? */
  2322. X    if (file_name[0] == '\0') {
  2323. X        putc_line(CAN);
  2324. X        return(0);
  2325. X    }
  2326. X    /*
  2327. X     * The file length is placed after the NULL of the file name
  2328. X     * and is terminated by another NULL.  If the length is missing,
  2329. X     * atol() will see a NULL and return 0.
  2330. X     */
  2331. X    length_is_at = strlen((char *) &buf[3]) + 4;
  2332. X    file_length = atol((char *) &buf[length_is_at]);
  2333. X    return(0);
  2334. X}
  2335. X
  2336. X/*
  2337. X * Handle file name collisions.  Prepend an "X" to the name until you find
  2338. X * a name that doesn't already exist.  Creates a NULL name on error.
  2339. X * Loads the global character array "file_name".
  2340. X */
  2341. X
  2342. Xvoid
  2343. Xchange_name(win, str)
  2344. XWINDOW *win;
  2345. Xchar *str;
  2346. X{
  2347. X    extern char file_name[15];
  2348. X    register int i;
  2349. X    int modified;
  2350. X    char temp[15], ans[15], *s, *strrchr(), *strcpy(), *strncat();
  2351. X    unsigned int sleep();
  2352. X                    /* dissect the name component */
  2353. X    if ((s = strrchr(str, '/')))
  2354. X        strcpy(temp, ++s);
  2355. X    else
  2356. X        strcpy(temp, str);
  2357. X
  2358. X    strcpy(ans, temp);
  2359. X    file_name[0] = '\0';
  2360. X                    /* write permission on directory? */
  2361. X    if (access(".", 2)) {
  2362. X        beep();
  2363. X        clear_line(win, 12, 24, TRUE);
  2364. X        wattrstr(win, A_BOLD, "NO WRITE ON DIRECTORY");
  2365. X        wrefresh(win);
  2366. X        return;
  2367. X    }
  2368. X                    /* prepend up to 13 "X"s */
  2369. X    modified = 0;
  2370. X    for (i=1; i<14; i++) {
  2371. X        if (access(ans, 0)) {
  2372. X            if (modified) {
  2373. X                beep();
  2374. X                clear_line(win, 12, 24, TRUE);
  2375. X                waddstr(win, "NAME COLLISION");
  2376. X                wrefresh(win);
  2377. X                sleep(1);
  2378. X            }
  2379. X            strcpy(file_name, ans);
  2380. X            return;
  2381. X        }
  2382. X
  2383. X        modified++;
  2384. X        strcpy(temp, "X");
  2385. X        strncat(temp, ans, 13);
  2386. X        temp[14] = '\0';
  2387. X        strcpy(ans, temp);
  2388. X    }
  2389. X    beep();
  2390. X    clear_line(win, 12, 24, TRUE);
  2391. X    waddstr(win, "BAD NAME");
  2392. X    wrefresh(win);
  2393. X    return;
  2394. X}
  2395. X
  2396. X/*
  2397. X * Convert a perfectly good Unix file name to fit the CP/M file name
  2398. X * rules.  Used for the modem7 batch file transfer.  Returns a pointer
  2399. X * to a static area containing the new name.
  2400. X */
  2401. X
  2402. Xchar *
  2403. Xfix_name(path)
  2404. Xchar *path;
  2405. X{
  2406. X    int dot;
  2407. X    char *s, *name, temp[15], *ext, *strcpy(), *strrchr();
  2408. X    static char ans[13];
  2409. X                    /* ignore the path component */
  2410. X    if (s = strrchr(path, '/'))
  2411. X        strcpy(temp, ++s);
  2412. X    else
  2413. X        strcpy(temp, path);
  2414. X    name = temp;
  2415. X
  2416. X    ext = "";
  2417. X    dot = 0;
  2418. X    for (s=name; *s; ++s) {
  2419. X        if (*s == '.' && !dot) {
  2420. X            dot++;
  2421. X            *s = '\0';
  2422. X            ext = s + 1;
  2423. X        }
  2424. X        if (islower(*s))
  2425. X            *s = toupper(*s);
  2426. X    }
  2427. X                    /* if null name component */
  2428. X    if (*name == '\0')
  2429. X        name = "X";
  2430. X                    /* if name too long */
  2431. X    if (strlen(name) > 8)
  2432. X        *(name+8) = '\0';
  2433. X                    /* if extension too long */
  2434. X    if (strlen(ext) > 3)
  2435. X        *(ext+3) = '\0';
  2436. X
  2437. X    sprintf(ans, "%-8.8s%-3.3s%c", temp, ext, CTRLZ);
  2438. X    return(ans);
  2439. X}
  2440. X
  2441. X/*
  2442. X * Convert a CP/M style filename into a legal Unix file name.  Loads the
  2443. X * global character array "file_name".
  2444. X */
  2445. X
  2446. Xvoid
  2447. Xunfix_name(cpm_name)
  2448. Xchar *cpm_name;
  2449. X{
  2450. X    extern char file_name[15];
  2451. X    register int i, n;
  2452. X    int dot;
  2453. X    char temp[15];
  2454. X
  2455. X    file_name[0] = '\0';
  2456. X    if (*cpm_name == '\0')
  2457. X        return;
  2458. X
  2459. X    strcpy(temp, cpm_name);
  2460. X                    /* 8 character of the name */
  2461. X    n = 0;
  2462. X    for (i=0; i<8; i++) {
  2463. X        if (temp[i] != ' ') {
  2464. X            if (isupper(temp[i]))
  2465. X                file_name[n++] = tolower(temp[i]);
  2466. X            else
  2467. X                file_name[n++] = temp[i];
  2468. X        }
  2469. X    }
  2470. X                    /* 3 character extension */
  2471. X    dot = 0;
  2472. X    for (i=8; i<11; i++) {
  2473. X        if (temp[i] != ' ') {
  2474. X            if (!dot) {
  2475. X                dot++;
  2476. X                file_name[n++] = '.';
  2477. X            }
  2478. X            if (isupper(temp[i]))
  2479. X                file_name[n++] = tolower(temp[i]);
  2480. X            else
  2481. X                file_name[n++] = temp[i];
  2482. X        }
  2483. X    }
  2484. X    file_name[n] = '\0';
  2485. X    return;
  2486. X}
  2487. SHAR_EOF
  2488. if test 8686 -ne "`wc -c < 'x_batch.c'`"
  2489. then
  2490.     echo shar: "error transmitting 'x_batch.c'" '(should have been 8686 characters)'
  2491. fi
  2492. fi
  2493. echo shar: "extracting 'x_extrnl.c'" '(2965 characters)'
  2494. if test -f 'x_extrnl.c'
  2495. then
  2496.     echo shar: "will not over-write existing file 'x_extrnl.c'"
  2497. else
  2498. sed 's/^X//' << \SHAR_EOF > 'x_extrnl.c'
  2499. X/*
  2500. X * Spawn a shell with the stdin and stdout swapped with the remote
  2501. X * system, ie:
  2502. X *                               +----------+
  2503. X *    TTYin ------------> stdin  |          |
  2504. X *                               |  shell   |
  2505. X *    TTYout <---------- stdout  |          |
  2506. X *                               +----------+
  2507. X *
  2508. X * An undocumented feature:  The external protocol gateway
  2509. X * can be used to pipe the output of a normal Unix command to the
  2510. X * remote system.
  2511. X */
  2512. X
  2513. X#include <stdio.h>
  2514. X#include <signal.h>
  2515. X#include <curses.h>
  2516. X#include <errno.h>
  2517. X#include "config.h"
  2518. X
  2519. X#ifdef BSD
  2520. X#include <sys/file.h>
  2521. X#else /* BSD */
  2522. X#include <fcntl.h>
  2523. X#endif /* BSD */
  2524. X
  2525. Xvoid
  2526. Xdo_extrnl(cmd)
  2527. Xchar *cmd;
  2528. X{
  2529. X    extern int fd, errno;
  2530. X    WINDOW *xt_win, *newwin();
  2531. X    SIG_TYPE (*istat)(), (*qstat)();
  2532. X    int epid, want_out, sig_status;
  2533. X    char buf[80], *ttyname(), *strcpy();
  2534. X    unsigned int sleep();
  2535. X    void _exit(), input_off();
  2536. X
  2537. X    input_off();
  2538. X                    /* a full window */
  2539. X    xt_win = newwin(LINES, COLS, 0, 0);
  2540. X    touchwin(xt_win);
  2541. X    wrefresh(xt_win);
  2542. X                    /* out of curses mode */
  2543. X    resetterm();
  2544. X
  2545. X    if (!(epid = fork())) {
  2546. X                    /* create a new process group ID */
  2547. X#ifdef BSD
  2548. X        setpgrp(0, getpid());
  2549. X#else /* BSD */
  2550. X        setpgrp();
  2551. X#endif /* BSD */
  2552. X                    /* recreate the device name */
  2553. X        strcpy(buf, ttyname(fd));
  2554. X        close(fd);
  2555. X                    /* swap the stdin */
  2556. X        close(0);
  2557. X#ifdef UNIXPC
  2558. X/*
  2559. X * Some strange things here... The OBM uses the second parameter of 
  2560. X * open() to determine if the port should be in the DATA mode or
  2561. X * the VOICE mode.  Therefore, we must always open with read and write.
  2562. X */
  2563. X        if (!strncmp(buf, "/dev/ph", 7))
  2564. X            open(buf, O_RDWR);
  2565. X        else
  2566. X#endif /* UNIXPC */
  2567. X        open(buf, O_RDONLY);
  2568. X                    /* swap the stdout */
  2569. X        close(1);
  2570. X#ifdef UNIXPC
  2571. X        if (!strncmp(buf, "/dev/ph", 7))
  2572. X            open(buf, O_RDWR);
  2573. X        else
  2574. X#endif /* UNIXPC */
  2575. X        open(buf, O_WRONLY);
  2576. X#ifdef SETUGID
  2577. X        setgid(getgid());
  2578. X        setuid(getuid());
  2579. X#endif /* SETUGID */
  2580. X        execl("/bin/sh", "sh", "-c", cmd, (char *) 0);
  2581. X        _exit(1);
  2582. X    }
  2583. X    istat = signal(SIGINT, SIG_IGN);
  2584. X    qstat = signal(SIGQUIT, SIG_IGN);
  2585. X
  2586. X    /*
  2587. X     * Check the keyboard while the external program is running.  If
  2588. X     * the user hits the <ESC> key, then kill the entire process
  2589. X     * group associated with the new shell.
  2590. X     */
  2591. X    want_out = 0;
  2592. X    while(1) {
  2593. X        switch(wait_key(stdscr, 1)) {
  2594. X            case -1:    /* timed out */
  2595. X                break;
  2596. X            case 27:    /* a user abort */
  2597. X#ifdef BSD
  2598. X                killpg(epid, SIGKILL);
  2599. X#else /* BSD */
  2600. X                kill(-epid, SIGKILL);
  2601. X#endif /* BSD */
  2602. X                want_out++;
  2603. X                break;
  2604. X            default:
  2605. X                beep();
  2606. X                break;
  2607. X        }
  2608. X        if (want_out)
  2609. X            break;
  2610. X                    /* see if the process it still active */
  2611. X#ifdef BSD
  2612. X        if ((kill(epid, 0) == -1) && errno == ESRCH) 
  2613. X#else /* BSD */
  2614. X        if ((kill(-epid, 0) == -1) && errno == ESRCH) 
  2615. X#endif /* BSD */
  2616. X            break;
  2617. X    }
  2618. X                    /* wait for the zombie process */
  2619. X    wait(&sig_status);
  2620. X
  2621. X    signal(SIGINT, istat);
  2622. X    signal(SIGQUIT, qstat);
  2623. X                    /* back to curses mode */
  2624. X    sleep(1);
  2625. X    fixterm();
  2626. X
  2627. X    clearok(curscr, TRUE);
  2628. X    werase(xt_win);
  2629. X    wrefresh(xt_win);
  2630. X    delwin(xt_win);
  2631. X    return;
  2632. X}
  2633. SHAR_EOF
  2634. if test 2965 -ne "`wc -c < 'x_extrnl.c'`"
  2635. then
  2636.     echo shar: "error transmitting 'x_extrnl.c'" '(should have been 2965 characters)'
  2637. fi
  2638. fi
  2639. exit 0
  2640. #    End of shell archive
  2641.  
  2642.  
  2643.